<html>
<head>
  <script src="../../lib/OpenLayers.js"></script>
  <script type="text/javascript">

    function test_constructor(t) {
        t.plan(11);
        var a = new OpenLayers.Protocol.Script({
            url: "foo"
        });

        // 7 tests
        t.eq(a.url, "foo", "constructor sets url");
        t.eq(a.options.url, a.url, "constructor copies url to options.url");
        t.eq(a.params, {}, "constructor sets params");
        t.eq(a.options.params, undefined, "constructor does not copy params to options.params");
        t.ok(a.format instanceof OpenLayers.Format.GeoJSON,
                "constructor sets a GeoJSON format by default");
        t.eq(a.callbackKey, 'callback',
                "callbackKey is set to 'callback' by default");
        t.eq(a.callbackPrefix, '',
                "callbackPrefix is set to '' by default");

        var params = {hello: "world"};
        var b = new OpenLayers.Protocol.Script({
            url: "bar",
            params: params,
            callbackKey: 'cb_key',
            callbackPrefix: 'cb_prefix'
        });

        // 6 tests
        t.eq(b.params, params, "constructor sets params");
        t.eq(b.options.params, b.params, "constructor copies params to options.params");
        t.eq(b.callbackKey, 'cb_key',
                "callbackKey is set to 'cb_key'");
        t.eq(b.callbackPrefix, 'cb_prefix',
                "callbackPrefix is set to 'cb_prefix'");
    }

    function test_destroy(t) {
        t.plan(3);
        var aborted = false;
        var protocol = new OpenLayers.Protocol.Script({
            url: "bar",
            params: {hello: "world"},
            abort: function() {
                aborted = true;
            }
        });
        protocol.destroy();
        t.ok(aborted, "destroy aborts request");
        t.eq(protocol.params, null, "destroy nullifies params");
        t.eq(protocol.format, null, "destroy nullifies format");
    }

    function test_read(t) {
        t.plan(5);
        var protocol = new OpenLayers.Protocol.Script({
            'url': 'foo_url',
            'params': {'k': 'foo_param'}
        });

        // fake XHR request object
        var request = {'status': 200};

        // options to pass to read
        var readOptions = {
            'url': 'bar_url',
            'params': {'k': 'bar_param'}
        };

        var response;

        protocol.createRequest = function(url, params, callback) {
            // 4 tests
            t.ok(this == protocol,
                'createRequest called with correct scope');
            t.ok(url == readOptions.url,
                'createRequest called with correct url');
            t.ok(params == readOptions.params,
                'createRequest called with correct params');
            t.ok(callback instanceof Function,
                'createRequest called with a function as callback');

            return 'foo_request';
       };

        var resp = protocol.read(readOptions);

        t.eq(resp.priv, 'foo_request',
            'response priv property set to what the createRequest method returns');
    }

    function test_read_bbox(t) {
        t.plan(6);

        var _createRequest = OpenLayers.Protocol.Script.prototype.createRequest;

        var bounds = new OpenLayers.Bounds(1, 2, 3, 4);
        var filter = new OpenLayers.Filter.Spatial({
            type: OpenLayers.Filter.Spatial.BBOX,
            value: bounds,
            projection: new OpenLayers.Projection("foo")
        });

        // log requests
        var log, exp;
        OpenLayers.Protocol.Script.prototype.createRequest = function(url, params,
                                                               callback) {
            log.push(params.bbox);
            return null;
        };

        // 1) issue request with default protocol
        log = [];
        new OpenLayers.Protocol.Script().read({filter: filter});

        t.eq(log.length, 1, "1) createRequest called once");
        t.ok(log[0] instanceof Array, "1) bbox param is array");
        exp = bounds.toArray();
        t.eq(log[0], exp, "1) bbox param doesn't include SRS id by default");

        // 2) issue request with default protocol
        log = [];
        new OpenLayers.Protocol.Script({srsInBBOX: true}).read({filter: filter});

        t.eq(log.length, 1, "2) createRequest called once");
        t.ok(log[0] instanceof Array, "2) bbox param is array");
        exp = bounds.toArray();
        exp.push("foo");
        t.eq(log[0], exp, "2) bbox param includes SRS id if srsInBBOX is true");

        OpenLayers.Protocol.Script.prototype.createRequest = _createRequest;
    }

    function test_createRequest(t) {
        t.plan(6);
        var protocol = new OpenLayers.Protocol.Script({
            callbackKey: 'cb_key',
            callbackPrefix: 'cb_prefix:'
        });

        var _register = OpenLayers.Protocol.Script.register;
        OpenLayers.Protocol.Script.register = function() {
            return 'bar';
        };

        var script = protocol.createRequest('http://bar_url/', {'k': 'bar_param'}, 'bar_callback');

        t.eq(script.type, 'text/javascript',
            'created script has a correct type');

        var params = OpenLayers.Util.getParameters(script.src);        
        t.eq(params.k, "bar_param", "custom query string param");
        t.eq(params.cb_key, "cb_prefix:OpenLayers.Protocol.Script.registry.bar", "callback with prefix");

        t.eq(script.id, 'OpenLayers_Protocol_Script_bar',
            'created script has a correct id');

        protocol.callbackTemplate = "customCallback(${id})";
        script = protocol.createRequest('http://bar_url/', {'k': 'bar_param2'}, 'bar_callback');

        params = OpenLayers.Util.getParameters(script.src);        
        t.eq(params.k, "bar_param2", "custom query string param");
        t.eq(params.cb_key, "cb_prefix:customCallback(bar)", "custom callback with prefix");

        OpenLayers.Protocol.Script.register = _register;

    }

    function test_destroyRequest(t) {
        t.plan(2);

        var protocol = new OpenLayers.Protocol.Script({});

        var _unregister = OpenLayers.Protocol.Script.unregister;
        OpenLayers.Protocol.Script.unregister = function(id) {
            t.eq(id, 'foo', "destroyRequest calls unregister with correct id");
        };
        var script = {
            id: 'script_foo'
        };
        protocol.destroyRequest(script);
        t.eq(protocol.pendingRequests[script.id], null, 
            "destroyRequest nullifies the pending request");

        OpenLayers.Protocol.Script.unregister = _unregister;
    }

    function test_handleResponse(t) {
        t.plan(8);

        var protocol = new OpenLayers.Protocol.Script();

        // 2 tests (should be called only twive)
        protocol.destroyRequest = function(priv) {
            t.eq(priv, 'foo_priv', 'destroyRequest called with correct argument');
        }

        // 1 test (should be called only once)
        protocol.parseFeatures = function(data) {
            t.eq(data, 'foo_data', 'parseFeatures called with correct argument');
            return 'foo_features';
        }

        var response = {
            priv: 'foo_priv',
            data: 'foo_data'
        }
        var options = {
            // 2 tests (should be called twice)
            scope: 'foo_scope',
            callback: function(resp) {
                t.eq(this, 'foo_scope', 'callback called with correct scope');
            }
        }
        protocol.handleResponse(response, options);
        // 2 tests
        t.eq(response.code, OpenLayers.Protocol.Response.SUCCESS,
                'response code correctly set');
        t.eq(response.features, 'foo_features', 
                'response features takes a correct value');

        response = {
            priv: 'foo_priv'
        }
        protocol.handleResponse(response, options);
        // 1 test
        t.eq(response.code, OpenLayers.Protocol.Response.FAILURE,
                'response code correctly set');
    }

    function test_parseFeatures(t) {
        t.plan(1);

        var protocol = new OpenLayers.Protocol.Script();

        protocol.format = {
            'read': function(data) {
                t.ok(true, 'format.read called');
            }
        };

        var ret = protocol.parseFeatures({foo: 'bar'});
    }

    function test_abort(t) {
        t.plan(2);

        var protocol = new OpenLayers.Protocol.Script();

        // 1 test
        protocol.destroyRequest = function(priv) {
            t.eq(priv, 'foo_priv', 'destroyRequest called with correct argument');
        }

        var response = {
            priv: 'foo_priv'
        }

        protocol.abort(response);

        var calls = [];
        protocol.pendingRequests = {
            'foo': 'foo_request',
            'bar': 'bar_request'
        }
        protocol.destroyRequest = function(priv) {
            calls.push(priv);
        }
        protocol.abort();
        // 1 test
        t.eq(calls, ['foo_request', 'bar_request'],
                'destroyRequest called for each pending requests');
    }

  </script>
</head>
<body>
</body>
</html>
